home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / sample code / files / putawayvolumes / putawayvolumes.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  7.2 KB  |  264 lines

  1. /*
  2.     File:        PutAwayVolumes.c
  3.     
  4.     Description:This code sample demonstrates several ways to unmount a volume.
  5.                 [1]        Call MoreFiles and have it take its best shot.
  6.                 [2]        Augment MoreFiles with a little Finder-style interface
  7.                         and some strategic trash-emptying.
  8.                 [3]        Send an AppleEvent to Finder and have it do the whole thing.
  9.                 
  10.                 A real strategy might use all of the above. Basically, the problem is
  11.                 this: although UnmountVol has been patched so that some commonly open
  12.                 files (mostly having to do with desktop info) are closed before the
  13.                 volume unmounts, not all are, and in particular files associated
  14.                 with the trash on shared volumes are not automagically closed.
  15.         
  16.                 Each of the three above-mentioned methods has its flaws.
  17.         
  18.                 [1]        It wouldn't be in the spirit of MoreFiles to empty
  19.                         the trash silently when attempting to unmount, so it's
  20.                         not surprising MoreFiles doesn't do it.
  21.     
  22.                 [2]        Getting confirmation from the user involves posting an
  23.                         alert, which is not always easy for non-apps.
  24.         
  25.                 [3]        Requires the unmounter to send AppleEvents, which is
  26.                         not always easy for non-apps, and may require user to
  27.                         switch to Finder to confirm alerts, which also is not
  28.                         always easy for non-apps.
  29.         
  30.                 Your program may have to combine methods to achieve the effect it
  31.                 needs. And your program should be ready for the methods to fail --
  32.                 not that you should expect a proper implementation to fail, but
  33.                 your program shouldn't assume that it will not.
  34.         
  35.                 Of course, if some application other than Finder or At Ease has files
  36.                 open on the volume, the volume simply will not unmount, and that's a
  37.                 legitimate error condition.
  38.     
  39.                 Note this sample in its current state will unmount all AppleShare
  40.                 volumes. The interesting function is PutAwayOneVolume, and it has
  41.                 nothing to do with AppleShare in particular. The rest of the functions
  42.                 are here simply to drive PutAwayOneVolume.
  43.  
  44.     Author:        PG
  45.  
  46.     Copyright:     Copyright: © 1996-1999 by Apple Computer, Inc.
  47.                 all rights reserved.
  48.     
  49.     Disclaimer:    You may incorporate this sample code into your applications without
  50.                 restriction, though the sample code has been provided "AS IS" and the
  51.                 responsibility for its operation is 100% yours.  However, what you are
  52.                 not permitted to do is to redistribute the source as "DSC Sample Code"
  53.                 after having made changes. If you're going to re-distribute the source,
  54.                 we require that you make it clear in the source that the code was
  55.                 descended from Apple Sample Code, but that you've made changes.
  56.     
  57.     Change History (most recent first):
  58.                 6/25/99        Updated for Metrowerks Codewarror Pro 2.1(KG)
  59.                 
  60.                 03/20/96    St. Luther points out that 'hpbp->volumeParam.ioVFSID'
  61.                             is not a sufficient test for AppleShare; check the driver
  62.                             name instead; this makes the sample a little more accurate
  63.                             but a little less useful, since nobody specifies volumes
  64.                             by driver name. However, the portion of this code which
  65.                             cares about which volumes to unmount is only here to make
  66.                             the sample run anyway; users will have to adapt this code
  67.                             regardless; PutAwayOneVolume is the interesting code, and
  68.                             it's not affected by this change.(PG)
  69.     
  70.                 03/20/96    PutAwayVolumes doesn't really need to know the names of the
  71.                             volumes it's indexing. Save some stack.(PG)
  72.     
  73.                 03/21/96    Use MoreFiles version of UnmountAndEject. Keeping my own
  74.                             copy was just stupid, especially since I plan to use more
  75.                             of MoreFiles.(PG)
  76.     
  77.                 03/21/96    After conversation with Jim, realized the AppleEvent
  78.                             strategy is not always best. This version makes use of
  79.                             semi-documented 'ReleaseFolder' call to deal with shared
  80.                             trash folders.(PG)
  81.  
  82. */
  83. #define OLDROUTINELOCATIONS        0
  84. #define OLDROUTINENAMES            0
  85. #define SystemSevenOrLater        1
  86.  
  87. #ifndef __FILES__
  88. #    include <Files.h>
  89. #endif
  90.  
  91. #ifndef __LOWMEM__
  92. #    include <LowMem.h>
  93. #endif
  94.  
  95. #ifndef __DEVICES__
  96. #    include <Devices.h>
  97. #endif
  98.  
  99. #ifndef __PLSTRINGFUNCS__
  100. #    include <PLStringFuncs.h>
  101. #endif
  102.  
  103. #ifndef __PROCESSES__
  104. #    include <Processes.h>
  105. #endif
  106. #ifndef __DIALOGS__
  107. #    include <Dialogs.h>
  108. #endif
  109. #include "PutAwayOneVolume.h"
  110.  
  111. #define USE_INTERNAL_CODE 1
  112.  
  113. //
  114. //    USE_INTERNAL_CODE controls whether we send the AppleEvent to Finder
  115. //    or use the internal code to unmount the volume ('ReleaseFolder').
  116. //
  117.  
  118. enum
  119. {
  120.     kCreatorCode_Finder = 'MACS',
  121.     kCreatorCode_AtEase = 'mfdr'
  122. };
  123.  
  124. static pascal OSErr GetCreatorOfFinderLikeProcess (OSType *processSignature)
  125. {
  126.     OSErr err = noErr;
  127.  
  128. #if !USE_INTERNAL_CODE
  129.  
  130.     ProcessSerialNumber        psn        = { kNoProcess, kNoProcess };
  131.     ProcessInfoRec            pir        = { sizeof (pir), nil };
  132.  
  133. #endif
  134.  
  135.     *processSignature = 0;
  136.  
  137. #if !USE_INTERNAL_CODE
  138.  
  139.     pir.processAppSpec = nil;
  140.  
  141.     for (;;)
  142.     {
  143.         err = GetNextProcess (&psn);
  144.         if (err)
  145.         {
  146.             if (err == procNotFound) err = noErr;
  147.             break;
  148.         }
  149.  
  150.         err = GetProcessInformation (&psn,&pir);
  151.         if (err) break;
  152.  
  153.         if (pir.processSignature == kCreatorCode_Finder || pir.processSignature == kCreatorCode_AtEase)
  154.         {
  155.             *processSignature = pir.processSignature;
  156.             break;
  157.         }
  158.     }
  159.  
  160. #endif
  161.  
  162.     return err;
  163. }
  164.  
  165. static pascal Boolean VolDriverNameIs (short vRefNum, ConstStr255Param potentialDriverName)
  166. {
  167.     Boolean result = false;
  168.  
  169.     const VCB *vcbQueueScanner = (const VCB *) GetVCBQHdr ( )->qHead;
  170.  
  171.     while (vcbQueueScanner)
  172.     {
  173.         if (vcbQueueScanner->vcbVRefNum == vRefNum)
  174.         {
  175.             short csParam [11];
  176.  
  177.             if (!Status (vcbQueueScanner->vcbDRefNum,1,csParam))
  178.             {
  179.                 DCtlHandle            dCtlHandle        = *(DCtlHandle *) csParam;
  180.                 DRVRHeaderPtr        drvrHeaderPtr    = (DRVRHeaderPtr) (**dCtlHandle).dCtlDriver;
  181.                 Boolean                isHandle        = (**dCtlHandle).dCtlFlags & dRAMBasedMask;
  182.                 ConstStr255Param    drvrName        = drvrHeaderPtr->drvrName;
  183.                 SInt8                hState;
  184.  
  185.                 //
  186.                 //    We lock the driver handle temporarily in case
  187.                 //    <PLStringFuncs.glue.lib> (which contains
  188.                 //    the implementation of PLstrcmp) lives in
  189.                 //    another (potentially unloaded) code segment.
  190.                 //
  191.  
  192.                 if (isHandle)
  193.                 {
  194.                     hState = HGetState ((Handle) drvrHeaderPtr);
  195.                     HLock ((Handle) drvrHeaderPtr);
  196.                     drvrName = (**(DRVRHeaderHandle)drvrHeaderPtr).drvrName;
  197.                 }
  198.  
  199.                 result = !PLstrcmp (potentialDriverName,drvrName);
  200.  
  201.                 if (isHandle)
  202.                     HSetState ((Handle) drvrHeaderPtr, hState);
  203.             }
  204.         }
  205.  
  206.         vcbQueueScanner = (const VCB *) (vcbQueueScanner->qLink);
  207.     }
  208.  
  209.     return result;
  210. }
  211.  
  212. static pascal OSErr PutAwayVolumes (const unsigned char *driverName)
  213. {
  214.     OSErr err = noErr;
  215.  
  216.     OSType finderLikeProcess;
  217.  
  218.     if (!(err = GetCreatorOfFinderLikeProcess (&finderLikeProcess)))
  219.     {
  220.         HParmBlkPtr hpbp = (HParmBlkPtr) NewPtrClear (sizeof (*hpbp));
  221.         if (!(err = MemError ( )))
  222.         {
  223.             hpbp->volumeParam.ioVolIndex = 1;
  224.     
  225.             for (;;)
  226.             {
  227.                 err = PBHGetVInfoSync (hpbp);
  228.                 if (err)
  229.                 {
  230.                     if (err == nsvErr) err = noErr;
  231.                     break;
  232.                 }
  233.     
  234.                 if (VolDriverNameIs (hpbp->volumeParam.ioVRefNum, driverName))
  235.                 {
  236.                     err = PutAwayOneVolume (hpbp->volumeParam.ioVRefNum, finderLikeProcess);
  237.                     if (err) break;
  238.                 }
  239.     
  240.                 hpbp->volumeParam.ioVolIndex += 1;
  241.             }
  242.     
  243.             DisposePtr ((Ptr) hpbp);
  244.             if (!err) err = MemError ( );
  245.         }
  246.     }
  247.  
  248.     return err;
  249. }
  250.  
  251. void main (void)
  252. {
  253.     MaxApplZone ( );
  254.     InitGraf (&(qd.thePort));
  255.     InitFonts ( );
  256.     InitWindows ( );
  257.     InitMenus ( );
  258.     TEInit ( );
  259.     InitDialogs (nil);
  260.  
  261. //    (void) PutAwayVolumes ("\p.Sony");
  262.  
  263.     (void) PutAwayVolumes ("\p.AFPTranslator");
  264. }